using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Practices.RecipeFramework;
using System.Runtime.Serialization;
using VSSDKAssist.Assets.References;
using EnvDTE;
using Microsoft.VisualStudio.Shell.Design;
using Microsoft.VisualStudio.Shell.Interop;
using System.Runtime.InteropServices;
using System.ComponentModel.Design;
using System.Collections;
using Microsoft.VisualStudio.Shell;
using VSSDKAssist.Assets.Helpers;
using Microsoft.VisualStudio.Modeling.Shell;
using VSSDKAssist.Assets.References.Base;

namespace VSSDKAssist.Recipes.Common.References
{
	/// <summary>
	/// UnboundReference for a Dsl project or folder
	/// </summary>
	[Serializable]
	public class DslProjectOrFolderReference : RecipeReferenceBase
	{
		#region Constants
		private const string DslExtension = ".dsl";
		#endregion

		#region Constructors
		/// <summary>
		/// Initializes a new instance of the <see cref="DslProjectOrFolderReference"/> class.
		/// </summary>
		/// <param name="recipe">The recipe.</param>
		public DslProjectOrFolderReference(String recipe) : base(recipe) { }
		#endregion

		#region Public Implementation
		/// <summary>
		/// Determines whether the reference is enabled for a particular target item,
		/// based on the condition contained in the reference.
		/// </summary>
		/// <param name="target">The <see cref="T:System.Object"/> to check for references.</param>
		/// <returns>
		/// 	<see langword="true"/> if the reference is enabled for the given <paramref name="target"/>.
		/// Otherwise, <see langword="false"/>.
		/// </returns>
		public override bool IsEnabledFor(object target)
		{
			Project project = target as Project;

			if(project == null)
			{
				ProjectItem projectItem = target as ProjectItem;

				if(projectItem != null && projectItem.Kind == EnvDTE.Constants.vsProjectItemKindPhysicalFolder)
				{
					return IsDslProject(projectItem.ContainingProject);
				}
			}
			else
			{
				return IsDslProject(project);
			}

			return false;
		}

		/// <summary>
		/// See <see cref="P:Microsoft.Practices.RecipeFramework.IAssetReference.AppliesTo"/>.
		/// </summary>
		/// <value></value>
		public override String AppliesTo
		{
			get { return Properties.Resources.DslProjectReference; }
		}
		#endregion

		#region Private Implementation
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
		private bool IsDslProject(Project project)
		{
			//Try to see if it is a Dsl Language Project
			ProjectItemIterator iterator = new ProjectItemIterator(project);

			foreach(ProjectItem projectItem in iterator)
			{
				try
				{
					if(projectItem.Properties.Item("Extension").Value.ToString().Equals(
						DslExtension, StringComparison.OrdinalIgnoreCase))
					{
						return true;
					}
				}
				catch
				{
					//Do nothing, goto the next ProjectItem
				}
			}

			//Now try to see if it is a DSL Package Project
			try
			{
				TypeDiscoveryHelper typeDiscoveryHelper = new TypeDiscoveryHelper(this.Site as IServiceProvider);
				ICollection types = typeDiscoveryHelper.GetTypes(typeof(ModelingPackage));

				foreach(Type type in types)
				{
					if(type.Assembly.ManifestModule.Name.Equals(
						project.Properties.Item("OutputFileName").Value.ToString(), StringComparison.OrdinalIgnoreCase))
					{
						return true;
					}
				}
			}
			catch
			{
				return false;
			}

			return false;
		}
		#endregion

		#region ISerializable Members

		/// <summary>
		/// Required constructor for deserialization.
		/// </summary>
		protected DslProjectOrFolderReference(SerializationInfo info, StreamingContext context)
			: base(info, context)
		{
		}

		#endregion ISerializable Members
	}
}
